﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace WayneGameSolution.Communicate.Tcp
{
    class TcpLinkListener:LinkListener ,ILinkListener 
    {
        System.Net.Sockets.Socket  Listener;
        SocketAsyncEventArgs AcceptCargo = new SocketAsyncEventArgs();
        TcpLinkListener(Dictionary<string,string > paramsDic ) :base (paramsDic)
        { }


        private bool stated=false ;
        public override void Start()
        {
            AcceptCargo.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptCargo_Completed);
            var ip = new IPEndPoint(IPAddress.Any, Port);
            Listener = new Socket(ip.AddressFamily , SocketType.Stream, ProtocolType.Tcp);
            Listener.Bind (ip);
            Listener.Listen(1024);
            Listener.AcceptAsync (AcceptCargo); 
               
            stated = true;
        }

        void AcceptCargo_Completed(object sender, SocketAsyncEventArgs e)
        {
            var socket = e.AcceptSocket ;
            TcpServerSideLink lk =
                new TcpServerSideLink(socket, LinkProveString, TimeoutSecond)
                {
                    Cryptography = DefaultCrypt,
                    PackCodec = DefaultCodec,
                    Status = LinkStatus.Ready,
                    User = null

                };


            ClientLinkProvePool.AddLast(lk);
            CheckTimeoutedLinks();

            Listener.AcceptAsync(AcceptCargo); 

            if (!stated)
            {
                this.Stop();

            }
        }



        private LinkedList<IServerSideLink> ClientLinkProvePool =new LinkedList<IServerSideLink>();

        private void CheckTimeoutedLinks()
        {
            while (this.ClientLinkProvePool.Count > 0)
            {
                TcpServerSideLink lk = (TcpServerSideLink)this.ClientLinkProvePool.First.Value;
                if (DateTime.Compare(lk.LastDataTime.AddSeconds((double)this.TimeoutSecond), DateTime.Now) >= 0)
                    break;

                this.ClientLinkProvePool.RemoveFirst();
                if (!lk.IsLinkProved)
                    lk.Close();
      
            }
        }

 

 


        public string LinkProveString
        {
            get
            {
                return this.paramsDic["LinkProveString"];
            }
        }
        public int Port
        {
            get
            {
                int p;
                if (int.TryParse(this.paramsDic["Port"], out p))
                {
                    return p;
                }
                return -1;
            }
        }


        int _TimeoutSecond=-1;
        public int TimeoutSecond
        {
            get
            {
                if (_TimeoutSecond==-1)
                    if (!int.TryParse(this.paramsDic["TimeoutSecond"], out _TimeoutSecond))
                    {
                        _TimeoutSecond = -1;
                    }

                return _TimeoutSecond;
            }
        }
 

 


 

        public override void Stop()
        {
            stated = false;
            
        }
    }
}
